<!-- 开发环境版本，包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

<body>
    <div id="app">
        {{ message }}
        <component-demo></component-demo>
        <component-demo1 :int-prop="parentObj.int" :obj-prop="parentObj" @outemit="parentOutemit"></component-demo1>
        <component-demo2></component-demo2>

        <ul>
            <!-- 有些 HTML 元素，诸如 <ul>、<ol>、<table> 和 <select>，对于哪些元素可以出现在其内部是有严格限制的 没有报错 -->
            <component-demo2></component-demo2>
            <li is="component-demo2"></li>
            <li :is="switchComonent"></li>
            <!--tab 组件切换-->
        </ul>
    </div>
</body>

<script type="x-template" id="componentDemo1">
    <h1 @click="clickEvent">自定义组件!</h1>
</script>

<script type="x-template" id="componentDemo2">
    <h1>自定义组件2!</h1>
</script>

<script>
    /**
     * data定义: 查看示例,return新对象防止组件多次使用时,data被关联对象
     * 模板定义template: 1.直接字符串行 2.x-template
     * 
     * props:输入
     *      1.父组件单向影响子组件  props不修改　
     *          如子组件只是单纯传一个初始值，并不想受父组件影响　在钩子created重新赋值
     *      2.子组件传父组件使用自定义事件 emit
     *      3.数组,对象是引用传递 对象里的值可以修改
     *      类型定义:
     *          String  Number  Boolean Array   Object  Date  Function Symbol
     *      规范定义后缀必须prop
     *          默认: nameProp 
     *          prop脱离父组件的影响 初始化 nameIntProp
     *          
     *      props:{
     *             objProp:[Object] 
     *      }
     * 
     * 事件
     *  template 用简写@替代v-click
     *  methods 
     *      Event后缀
     *      emit 通知
     *          Outemit 通知父组件
     *              this.$emit('outemit');
     *          Inemit  被子组件通知
     *      //方法
     *      
     *  
     * */

    /**
     *  组件可测试性 带默认值 暂时不带，通过模板调用传递
     * **/

    // 全局注册
    Vue.component('componentDemo', {
        props: [

        ],
        data() {
            return {

            };
        },
        template: '<h1>自定义组件!</h1>'
    })
    Vue.component('componentDemo1', {
        props: {
            intProp: [Number],
            strProp: [String],
            objProp: [Object], //备注参数不推荐
            mixProp: [Number, String],
            defaultProp: { //带默认值
                type: String,
                default: 'success',
                validator: function (value) {
                    //当 prop 验证失败的时候，(开发环境构建版本的) Vue 将会产生一个控制台的警告。
                    // 这个值必须匹配下列字符串中的一个
                    return ['success', 'warning', 'danger'].indexOf(value) !== -1
                }
            },
        },
        data() {
            return {

            };
        },
        template: '#componentDemo1',
        created() {
            console.log(this.intProp);
            console.log(this.objProp.str);
            this.objProp.str = 'update';
            console.log(this.objProp.str);
            console.log(this.mixProp);
        },
        methods: {
            //event
            clickEvent: function () {
                alert('EventDemo');
                console.log(this.intProp);
                this.outemit();

            },
            //emit
                //通知父组件
            outemit: function () {
                console.log('outemit');
                this.$emit('outemit','1','2');
            },
                //子组件通知
            inemit:function(){
            }
        }
    });

    //局部注册
    var componentDemo2 = Vue.extend({
        props: [

        ],
        data() {
            return {

            };
        },
        template: '#componentDemo2'
    });

    var app = new Vue({
        el: '#app',
        data: {
            message: 'Hello Vue!',
            parentObj: {
                int: 1,
                str: 'str',
                obj: {
                    int: 1,
                    str: 'str'
                }
            },
            switchComonent: "componentDemo2"
        },
        components: {
            //'component-demo2': componentDemo2
            componentDemo2
        },
        methods:{
            parentOutemit: function (item1,item2) {
                console.log(item1);
                console.log(item2);
                console.log('parentOutemit');
            }
        }
    });

</script>